/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package uk.ac.cam.can;

import uk.ac.cam.can.generalisator.Generalisator;
import java.io.*;
import java.util.*;

/**
 *
 * @author Thomas
 */
public class Data {
    public static int TYPE_QUASI_IDENTIFIER=0;
    public static int TYPE_SENSITIVE=1;
    public static int TYPE_NON_SENSITIVE=2;
    public static int TYPE_PSEUDO_IDENTIFIER=3;
    public static int TYPE_EVENT=4;
    
    private List<String[]> records = new ArrayList<String[]>();
    private int[] types;
    private Generalisator[] gens;
    int[] cost;
    private String fileName;
    private int[] currentGeneralisations;
    private String separator;
    
    public Data(String fileName, String separator, int[] types, Generalisator[] generalisators, int[] cost){
        this.separator=separator;
        this.types=types;
        this.gens=generalisators;
        this.fileName=fileName;
        currentGeneralisations = new int[types.length];
        this.cost=cost;
    }
    
    public void setRecords(List<String[]> records){
        this.records=records;
    }
    
    public void load(){
        try{
            File f = new File(fileName);
            DataInputStream in = new DataInputStream(new FileInputStream(f));
            BufferedReader buff = new BufferedReader(new InputStreamReader(in));

            String strLine;
            records.clear();
            while ((strLine = buff.readLine()) != null)   {
                String[] record = strLine.split(separator);
                records.add(record);
            }
        }catch(Exception e){
            System.out.println(e);
        }
        for(int i = 0; i < currentGeneralisations.length; i++){
            currentGeneralisations[i]=0;
        }
    }
    
    public void load(String newFile){
        this.fileName=newFile;
        this.load();
    }
    
    public int nbAttributes(){
        return types.length;
    }
    
    public int getType(int index){
        return types[index];
    }
    
    public int getMaxGeneralisation(int index){
        return gens[index].getMaxGeneralisation();
    }
    
    public List<String[]> getRecords(){
        return records;
    }
    
    public int getCost(int index){
        return cost[index];
    }
    
    public void remove(String[] record){
        records.remove(record);
    }
    
    public void removeAll(Collection<String[]> coll){
        records.removeAll(coll);
    }
    
    public int size(){
        return records.size();
    }
    
    public boolean generalise(int pos, int gen){
        if(gens[pos].getMaxGeneralisation() == currentGeneralisations[pos])
            return false;
        while(currentGeneralisations[pos]<gen){
            currentGeneralisations[pos]=currentGeneralisations[pos]+1;
            for(String[] record : records){
                record[pos]=gens[pos].gen(record[pos]);
            }
        }
        return true;
    }
    
    public double getLength(int index, String value){
        return gens[index].getLength(value);
    }
    
    public double getWorstQuality(){
        // fully generalised table quality
        double quality = 1.0;
        for(int i = 0; i < types.length; i++)
            quality*=gens[i].getMaxLength();
        return quality;
    }
    
    public void save(String fileName) throws Exception{
        File f = new File(fileName);
        f.delete();
        BufferedWriter buff = new BufferedWriter(new FileWriter(fileName));
        for(String[] record : records){
            String line="";
            for(String a : record){
                line+=a+separator;
            }
            buff.write(line);
            buff.newLine();
        }
        buff.flush();
        buff.close();
    }
    
    public void remove(double p){
        Random rand = new Random(System.nanoTime());
        int target=(int)((double)records.size()*p);
        while(target>0){
            int c = 50+rand.nextInt(500);
            int nb = rand.nextInt(records.size()-c);
            for(int i = nb; i < c && i < records.size(); i++){
                records.remove(i);
                target--;
            }
        }
    }
    
    public int getCurrentGeneralisation(int index){
        return currentGeneralisations[index];
    }
    
    public int getMaxCost(){
        int c = 0;
        for(int i=0; i < cost.length; i++){
            c+=cost[i]*gens[i].getMaxGeneralisation();
        }
        return c;
    }
    
    public int getNbQuasi(){
        int i=0;
        for(int type :types){
            if(type==Data.TYPE_QUASI_IDENTIFIER)
                i++;
        }
        return i;
    }
    
    public int[] getAttributeOrderByCost(){
        int[] result = new int[types.length];
        int[] tmp = new int[types.length];
        System.arraycopy(cost, 0, tmp, 0, types.length);
        
        Arrays.sort(tmp);
        int p =0;
        for(int i = types.length-1; i >= 0; i--){
            for(int j = 0; j < types.length; j++){
                if(tmp[i]==cost[j]){
                    result[p++]=j;
                }
            }
        }
        return result;
    }
    
    public String getSeparator(){
        return separator;
    }
    
    public void listOfRecordToFile(List<String[]> rs, String fileName) throws Exception{
        File f = new File(fileName);
        f.delete();
        BufferedWriter buff = new BufferedWriter(new FileWriter(fileName));
        for(String[] record : rs){
            String line="";
            for(String a : record){
                line+=a+separator;
            }
            buff.write(line);
            buff.newLine();
        }
        buff.flush();
        buff.close();
    }
    
    public int getNbAttribute(){
        return types.length;
    }

    public String mark(int attPos, String value, int val) {
        int g = getGeneralisationLevel(attPos, value);
        if(val==g)
            return value;
        if(val<g){
            String result=value;
            for(int i = g; i>=val; i--)
                result=gens[attPos].getUngeneralisation(result);
            return result;
        }else{
            String result=value;
            for(int tmp = this.getCurrentGeneralisation(attPos); tmp < val; tmp++)
                result=gens[attPos].gen(result);
            return result;
        }
    }

    public int getGeneralisationLevel(int attPos, String value) {
        return gens[attPos].getGeneralisationLevel(value);
    }
}
